package kpabe;

/**
 * @author anhdinh Wrapper for all the proxy-based KP-ABE functionality
 */
public class KPAbe {
	static {
		System.loadLibrary("proxyKPAbe");
	}

	// data owner API. Assume one sliding window size per owner. 
	public native byte[] initOwner(String[] attributeUniverse,
			int beta);

	public native byte[] enc_simple(String[] attributes, int value);

	//index of the record in the stream 0,1,2...
	public native byte[] enc_slidingWindow(String[] attributes, int value,
			int index); 

	public native byte[] extractOriginalCipher(byte[] cipher);
	
	//the TK used by the cloud
	public native byte[] generateTransformKey(String policy, int policyId); 

	//zu
	public native byte[] generateUserDecryptionKey(int policyId); 

	//sigma(alpha,beta)
	public native byte[] generateUserMaskValue(int alpha); 
	
	
	//data user API.
	public native void initUser_simple(byte[] pubK, byte[] tK, byte[] decK);
	
	public native void initUser_slidingWindow(byte[] pubK, byte[] tK,
			byte[] decK, byte[] mask, int beta);
	
	//pre-compute discrete-log solution: g^x -> x
	public native void initDiscreteLogMap(int max);
	
	//return -1 if invalid decryption, plaintext value otherwise
	public native int decrypt_simple(byte[] transformedCipher, byte[] originalCipher);
	
	public native int decrypt_slidingWindow(byte[] transformedCipher,
			byte[] originalCipher, int windowIndex);

	
	//cloud API. Each public parameter is mapped to a streamId, each user a policyId
	public native void initACInstance(byte[] pubK, int streamId, byte[] transformK, int policyId);
	
	public native byte[] transform_simple(byte[] ciphertext, int streamId, int policyId);
	
	public native byte[] multiplyCiphers(byte[][] ciphertexts, int streamId);
	
	public static void main(String[] argv){
		System.out.println("Hello world");
		String[] universe = new String[1];
		universe[0] = "x";
		
		String[] atts = new String[1];
		atts[0] = "x";
		KPAbe abeHandler = new KPAbe();
		long overallStart = System.currentTimeMillis();
		
		long ownerStart = System.currentTimeMillis();
		byte[] pubK = abeHandler.initOwner(universe, 2);
		long ownerEnd = System.currentTimeMillis();
		System.out.println("Onwer init time = "+(ownerEnd-ownerStart));
		byte[] cipher = abeHandler.enc_simple(atts, 250);
		byte[] ep = abeHandler.extractOriginalCipher(cipher);
		byte[] userK = abeHandler.generateUserDecryptionKey(0);
		byte[] tK = abeHandler.generateTransformKey("x", 0);
		long start = System.currentTimeMillis();
		abeHandler.initACInstance(pubK,0,tK,0);
		long end = System.currentTimeMillis();
		System.out.println("init cloud time = "+(end-start));
		
		start = System.currentTimeMillis();
		byte[] transformedCipher = abeHandler.transform_simple(cipher, 0, 0);
		end = System.currentTimeMillis();
		System.out.println("transform time = "+(end-start));
		
		start = System.currentTimeMillis();
		abeHandler.initUser_simple(pubK,tK,userK);
		end = System.currentTimeMillis();
		System.out.println("init user time = "+(end-start));

		System.out.println("Decryption result = "+abeHandler.decrypt_simple(transformedCipher, ep));
		long overallEnd = System.currentTimeMillis();
		System.out.println("Overall time = "+(overallEnd - overallStart));

	}
}
